using System;
using System.Globalization;
using System.Reflection;
using Prometheus.Binding.Core;

#if NETFX_CORE
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Markup;
#else
using System.Windows.Data;
using System.Windows.Markup;
#endif


namespace Prometheus.Binding.ReadOnly
{

    /// <summary>
    /// Can convert value, but still can not get or set value
    /// </summary>
    [ContentProperty(
#if NETFX_CORE
        Name = 
#endif
"Converter")]
    public abstract class proConvertableBinding : proBindingBase
    {
        protected proConvertableBinding(string elementPropertyPath, string dataContextPropertyPath)
            : base(elementPropertyPath, dataContextPropertyPath)
        {
        }

        /// <summary>
        /// Value converter
        /// </summary>
        public IValueConverter Converter { get; set; }

        /// <summary>
        /// Converter parameter will be passed to converter
        /// </summary>
        public object ConverterParameter
        {get; set; }

        /// <summary>
        /// get source type, if is not accesible - object
        /// </summary>
        protected Type SourceType
        {
            get
            {
                if (CurrentDataContext != null)
                {
                    PropertyInfo propertyInfo = CurrentDataContext.GetType()
#if NETFX_CORE
                                                                  .GetTypeInfo()
                                                                  .GetDeclaredProperty(Path);
#else
.GetProperty(Path);
#endif
                        
                    if (propertyInfo != null) return propertyInfo.PropertyType;
                }
                return typeof (object);
            }
        }

        /// <summary>
        /// Path to element property which must be bound
        /// </summary>
        public string ElementPropertyType { get; set; }

        /// <summary>
        /// get the target type, if is inaccesible - object
        /// </summary>
        protected Type TargetType
        {
            get
            {
                if (string.IsNullOrEmpty(ElementPropertyPath))
                {
                    throw new InvalidOperationException("Can not find default property for " +
                                                        UIElement.GetType().FullName);
                }

                if (!string.IsNullOrEmpty(ElementPropertyType)) return Type.GetType(ElementPropertyType);

                if (uiElement != null)
                {
                    PropertyInfo propertyInfo = uiElement.GetType()
#if NETFX_CORE
                                                         .GetTypeInfo()
                                                         .GetDeclaredProperty(ElementPropertyPath)
#else
.GetProperty(ElementPropertyPath)
#endif
                        ;
                    if (propertyInfo != null) return propertyInfo.PropertyType;
                }
                return typeof (object);
            }
        }



#if NETFX_CORE

        private string _language;
        public string Language
        {
            get { return _language; }
            set { _language = value; }
        }
#else
        private CultureInfo _culture;
        /// <summary>
        /// Culture will be passed to converter
        /// </summary>
        public CultureInfo Culture
        {
            get { return _culture; }
            set { _culture = value; }
        }
#endif
        

        /// <summary>
        /// Can be used to convert any value by the converter
        /// </summary>
        protected object Convert(object value)
        {
            if (Converter != null)
            {
                return Converter.Convert(value, TargetType, ConverterParameter, 
#if NETFX_CORE
                    Language
#else
 Culture
#endif
                    );
            }
            return value;
        }

        /// <summary>
        /// Can be used to do back-converting by the converter
        /// </summary>
        protected object ConvertBack(object value)
        {
            if (Converter != null)
                return Converter.ConvertBack(value, SourceType, ConverterParameter, 
#if NETFX_CORE
                    Language
#else
 Culture
#endif
 );
            return value;
        }

        /// <summary>
        /// Overrides parent Bindg method, and search for culture from the ui Element
        /// </summary>
        public override void Bind()
        {
#if NETFX_CORE
            if (uiElement != null) Language = uiElement.Language;
#else
            if (uiElement != null) _culture = new CultureInfo(uiElement.Language.IetfLanguageTag);
#endif
            base.Bind();
        }
    }
}